package ink.tiptop.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.trilead.ssh2.Connection;
import ink.tiptop.persist.domain.bo.LocalViewDto;
import ink.tiptop.persist.domain.entity.ZjfBaseServerInfoEntity;
import ink.tiptop.persist.domain.entity.ZjfServiceRemoteViewEntity;
import ink.tiptop.dto.req.remote.*;
import ink.tiptop.enums.EResp;
import ink.tiptop.common.domain.WebworkResponse;
import ink.tiptop.dto.resp.remote.ZjfServiceRemoteViewInfo;
import ink.tiptop.common.cache.CacheAble;
import ink.tiptop.common.cache.CacheEvict;
import ink.tiptop.common.cache.ECaches;
import ink.tiptop.common.cache.ICache;
import ink.tiptop.constant.Cmd;
import ink.tiptop.constant.Proof;
import ink.tiptop.persist.dao.ZjfModuleLocalViewMapper;
import ink.tiptop.persist.dao.ZjfServiceRemoteViewMapper;
import ink.tiptop.common.domain.req.PageRequest;
import ink.tiptop.common.domain.rsp.Response;
import ink.tiptop.service.AbstractBaseService;
import ink.tiptop.service.CacheSearch;
import ink.tiptop.service.ZjfBaseServerInfoService;
import ink.tiptop.service.ZjfServiceRemoteViewService;
import ink.tiptop.utils.ParamUtils;
import ink.tiptop.utils.ssh.SshUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;
import ink.tiptop.utils.JSON;
/**
 * 服务远程视图(ZjfServiceRemoteView)表服务实现类
 *
 * @author zjf
 * @since 2020-07-22 08:45:34
 */
@Service("zjfServiceRemoteViewService")
@Slf4j
public class ZjfServiceRemoteViewServiceImpl extends AbstractBaseService<ZjfServiceRemoteViewEntity> implements ZjfServiceRemoteViewService {

    private static final String CACHE_KEY = "REMOTE_VIEW";
    private static final String CACHE_CLEAR = CACHE_KEY + "*";
    // 维护一个排序字段映射,前端传递 PARENT -> 排序映射 parent
    private static final Map<String, String> orderByMap = new HashMap<>();

    static {
        orderByMap.put("PARENT", "parent");
        orderByMap.put("ORDER", "order");
        orderByMap.put("NAME", "name");
        orderByMap.put("IGNORE", "ignore");
    }

    @Resource
    private ZjfServiceRemoteViewMapper zjfServiceRemoteViewMapper;
    @Autowired
    private ZjfBaseServerInfoService zjfBaseServerInfoService;
    @Autowired
    private ICache<String> cache;
    @Resource
    private ZjfModuleLocalViewMapper moduleLocalViewMapper;

    /**
     * 通过ID查询单条数据
     *
     * @param id 主键
     * @return 实例对象
     */
    @Override
    public ZjfServiceRemoteViewEntity queryById(Integer id) {
        return this.zjfServiceRemoteViewMapper.selectById(id);
    }

    @Autowired
    private CacheSearch<ZjfServiceRemoteViewEntity> cacheSearch;

    /**
     * 查询多条数据
     *
     * @return 对象列表
     */
    @Override
    public List<ZjfServiceRemoteViewEntity> queryAll() {
        String cacheKey = CACHE_KEY+"ALL";
        List<ZjfServiceRemoteViewEntity> list = cacheSearch.getList(cacheKey, ZjfServiceRemoteViewEntity.class,ECaches.DAY);
        if (list == null) {
            list = zjfServiceRemoteViewMapper.selectList(null);
            cache.setVal(cacheKey, JSON.toJSONString(list), ECaches.DAY);
        }
        return list;
    }

    /**
     * 新增数据
     *
     * @param zjfServiceRemoteViewEntity 实例对象
     * @return 实例对象
     */
    @Override
    public ZjfServiceRemoteViewEntity insert(ZjfServiceRemoteViewEntity zjfServiceRemoteViewEntity) {
        this.zjfServiceRemoteViewMapper.insert(zjfServiceRemoteViewEntity);
        return zjfServiceRemoteViewEntity;
    }

    /**
     * 通过主键删除数据
     *
     * @param id 主键
     * @return 是否成功
     */
    @Override
    public boolean deleteById(Integer id) {
        return this.zjfServiceRemoteViewMapper.deleteById(id) > 0;
    }

    @Override
    @CacheAble(desc = "远程视图缓存注解", keyPrefix = CACHE_KEY,type = ECaches.DAY)
    public Response list(QueryZjfServiceRemoteViewRequest request) {
        return super.list(request);
    }

    /**
     * 排序
     *
     * @param request
     */
    @Override
    protected void setOrderBy(PageRequest request) {
//        if (StringUtils.isNoneBlank(request.getSortType())
//                && StringUtils.isNoneBlank(request.getSortName())) {
//            // 这里直接设置了排序,比如 create_time  desc
//            String orderByString = String.format(ORDER_BY_FORMAT, orderByMap.get(request.getSortName()), request.getSortType());
//            PageHelper.orderBy(orderByString);
//        }
    }

    /**
     * 组装请求参数
     *
     * @param request
     * @return
     */
    @Override
    protected ZjfServiceRemoteViewEntity getQueryParam(PageRequest request) {
        ZjfServiceRemoteViewEntity entity = new ZjfServiceRemoteViewEntity();
        BeanUtils.copyProperties(request, entity);
        if (StringUtils.isNotBlank(request.getSearch())) {
            entity.setName("%" + request.getSearch().trim() + "%");
        }
        return entity;
    }

    /**
     * 查询数据库,返回list
     *
     * @param param
     * @return
     */
    @Override
    protected Page<ZjfServiceRemoteViewEntity> getQueryEntityList(Page<ZjfServiceRemoteViewEntity> page,ZjfServiceRemoteViewEntity param) {
        QueryWrapper<ZjfServiceRemoteViewEntity> wrapper = new QueryWrapper<>(param);
        if (StringUtils.isNotBlank(param.getName())) {
            wrapper.like(true,"`name`",param.getName());
        }
        return zjfServiceRemoteViewMapper.selectPage(page,wrapper);
    }

    /**
     * 组装响应参数,这里其实是list,为了扩展 ,写成了Object
     *
     * @param voList
     * @return
     */
    @Override
    protected Object getResponseList(List<ZjfServiceRemoteViewEntity> voList) {
        List<ZjfServiceRemoteViewInfo> infos = new ArrayList<>();
        ZjfServiceRemoteViewInfo info;
        for (ZjfServiceRemoteViewEntity entity : voList) {
            info = new ZjfServiceRemoteViewInfo();
            BeanUtils.copyProperties(entity, info);
            infos.add(info);
        }
        return infos;
    }

    @CacheEvict(key = CACHE_CLEAR,type = ECaches.DAY)
    public Response update(UpdateZjfServiceRemoteViewRequest request) {
        ZjfServiceRemoteViewEntity entity = new ZjfServiceRemoteViewEntity();
        entity.setId(request.getId());
        int count = zjfServiceRemoteViewMapper.selectCount(new QueryWrapper<>(entity));
        BeanUtils.copyProperties(request, entity);
        if (count < 1) {
            return WebworkResponse.failed(EResp.EViewRemote.ERROR_EXIST_NOT);
        }
        int rows = 0;
        try {
            rows = zjfServiceRemoteViewMapper.updateById(entity);
        } catch (Exception e) {
            if (e instanceof DuplicateKeyException) {
                return WebworkResponse.failed(EResp.EViewRemote.ERROR_EXIST);
            }
        }
        if (rows > 0) {
            return WebworkResponse.SUCCEED;
        }
        return WebworkResponse.ERROR;
    }

    @CacheEvict(key = CACHE_CLEAR,type = ECaches.DAY)
    public Response delete(DeleteZjfServiceRemoteViewRequest request) {
        // 1. 请求删除的ID列表
        List<Integer> reqIdList = ParamUtils.toIntList(request.getId());

        // 2.查询到关联的id列表
        List<Integer> relatedIdList =  getRelatedList(request.getId());
        if (relatedIdList != null && !relatedIdList.isEmpty()) {
            // 请求删除的id列表 删除 关联的id列表 , 剩下的是可以都删除的
            List<Integer> delIdList = reqIdList.stream().filter(req -> !relatedIdList.contains(req)).collect(Collectors.toList());
            if (delIdList == null || delIdList.isEmpty()) {
                return WebworkResponse.failed(EResp.EViewRemote.ERROR_DELETE_FORBID);
            }
            int rows = zjfServiceRemoteViewMapper.deleteBatchIds(delIdList);
            if (rows > 0) {
                return WebworkResponse.failed(EResp.EViewRemote.ERROR_DELETE_PART);
            }
        } else {
            int rows = zjfServiceRemoteViewMapper.deleteBatchIds(reqIdList);
            if (rows > 0) {
                return WebworkResponse.SUCCEED;
            }
        }
        return WebworkResponse.ERROR;

    }

    private List<Integer> getRelatedList(List<String> reqIdList) {
        String ids = String.join(",", reqIdList);
        // 2.查询到关联的id列表
        return moduleLocalViewMapper.listRelatedIdList(ids);
    }

    @CacheEvict(key = CACHE_CLEAR,type = ECaches.DAY)
    public Response add(AddZjfServiceRemoteViewRequest request) {
        // TODO 这里要先判断数据的唯一
        ZjfServiceRemoteViewEntity entity = new ZjfServiceRemoteViewEntity();
        entity.setParent(request.getParent());
        entity.setName(request.getName());
        entity.setServerId(request.getServerId());
        int count = zjfServiceRemoteViewMapper.selectCount(new QueryWrapper<>(entity));
        if (count > 0) {
            return WebworkResponse.failed(EResp.EViewRemote.ERROR_EXIST);
        }
        BeanUtils.copyProperties(request, entity);
        int rows = zjfServiceRemoteViewMapper.insert(entity);
        if (rows > 0) {
            return WebworkResponse.SUCCEED;
        }
        return WebworkResponse.ERROR;
    }

    @Override
    @CacheEvict(key = CACHE_CLEAR,type = ECaches.DAY)
    public Response scan(ScanZjfServiceRemoteViewRequest request) {
        // 1.先查库,服务器信息
        ZjfBaseServerInfoEntity serverInfoEntity = zjfBaseServerInfoService.queryById(request.getServerId());
        if (serverInfoEntity == null) {
            return WebworkResponse.failed(EResp.EServerInfo.ERROR_EXIST_NOT);
        }
        try {
            // 2.获取连接
            Connection conn = zjfBaseServerInfoService.getConnection(serverInfoEntity);
            // 3.执行返回list 所有的项目根目录(包含了bin目录的)
//            List<String> serviceList = SshUtil.exec(conn, String.format(Cmd.FIND, request.getScanPath(), Proof.SEARCH_PROOF_META_INF));
            List<String> serviceList = SshUtil.exec(conn, String.format(Cmd.FIND, request.getScanPath(), request.getProof()));
            if (serviceList == null || serviceList.isEmpty()) {
                return WebworkResponse.failed(EResp.EViewRemote.ERROR_SCAN_ERROR);
            }
            // 4.都是标准的输出模式
            ZjfServiceRemoteViewEntity entity;
            for (String service : serviceList) {
                entity = new ZjfServiceRemoteViewEntity();
                String[] fullPath = service.split("\\/");
                if (fullPath.length < 3) {
                    continue;
                }
                String name = fullPath[fullPath.length - 2];
                entity.setParent(service.substring(0, service.lastIndexOf(name) - 1));
                entity.setName(name);
                entity.setServerId(request.getServerId());
                boolean exist = checkExist(entity);
                if (exist) {
                    continue;
                }
                entity.setLib(Proof.LIB);
                entity.setResource(request.getProof());
                entity.setBinStart(Proof.BIN_RESTART);
                entity.setBinStop(Proof.BIN_STOP);
                entity.setOrder(10);
                entity.setDesc("扫描添加");
                entity.setIgnore(0);
                try {
                    this.insert(entity);
                } catch (DuplicateKeyException e) {
                    log.error(e.getMessage(), e);
                    continue;
                }
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return WebworkResponse.ERROR;
        }
        return WebworkResponse.SUCCEED;
    }

    @Override
    public ZjfServiceRemoteViewEntity queryByUniqueIndex(ZjfServiceRemoteViewEntity serviceRemoteViewEntity) {
        List<ZjfServiceRemoteViewEntity> zjfServiceRemoteViewEntities = zjfServiceRemoteViewMapper.selectList(new QueryWrapper<>(serviceRemoteViewEntity));
        return zjfServiceRemoteViewEntities.isEmpty() ? null : zjfServiceRemoteViewEntities.get(0);
    }

    @Override
    public List<ZjfServiceRemoteViewEntity> getByLocalView(LocalViewDto dto) {
        return zjfServiceRemoteViewMapper.queryByLocalView(dto);
    }

    private boolean checkExist(ZjfServiceRemoteViewEntity entity) {
        return zjfServiceRemoteViewMapper.selectCount(new QueryWrapper<>(entity)) > 0;
    }

    @Override
    public void update(Observable o, Object arg) {
        log.info("预热ZjfServiceRemoteViewServiceImpl缓存");
        this.queryAll();
    }
}
